perm filename VDSK.FAI[CMS,LCS]1 blob sn#362803 filedate 1978-06-22 generic text, type T, neo UTF8
00100	;Floppy disk file system.
00200	.INSERT ASMBL.FAI[CMS,LCS]
00300	
00400	   ZERO ← 274	;Fail offset
00500	   LOC ZERO
00600	
00700	CBLK:	0	;Ram command block.
00800	CCNT:	0	;C parameter count.
00900	CTRK:	0	;C track
01000	CSEC:	0	;C sector
01100	CLEN:	0	;C length in sectors.
01200		BLOCK 3
01300	FCMD:	0	;Disk command pointer.
01400	FCMDH:	0
01500	CMD:	0	;File system command.
01502	CMDJMP:	0	;Indirect command jump.
01503	CJMPH:	0	;Msbyte.
01505	ERFLG:	0	;Error flag/code.
01550	RFOPEN:	0	;Read file open flag.
01600	WFOPEN:	0	;Write file open flag
01700	FLEN:	0	;File length. In sectors.
01800	SREM:	0	;Sectors remaining. In sectors.
01900	
02000	FBLK:	0	;File block
02100	FNAM:	BLOCK 11	;9 Chr file name.
02200	FTRK:	0	;Disk track number
02300	FSEC:	0	;Disk sector number
02400	NSEC:	0	;Number of sectors
02500		0
02600		0
02700		0
02800	
02900	DBLK:	0	;Directory block
03000	SCNT:	0	;Number of sectors
03100	FCNT:	0	;Number of files
03200	FFDIR:	0	;First free directory block
03300	FFTRK:	0	;First free data track
03400	FFSEC:	0	;First free data sector
03500	FBLKS:	0	;Number of free sectors. In sectors.
03600	
03700	SPOINT:	0	;SI/O pointer.
03800	SPOH:	0	;Msbyte
03900	DPOINT:	0	;Disk buffer bointer.
04000	DPOH:	0	;Msbyte
04100	
04200	   LOC ZERO+1000
04300	FBUF:	BLOCK 1000	;Disk buffer
     

00100	   LOC ZERO+17400	;PROM Start address.
00200	CMDTBL:
00300	   DINT ← 0
00400		65	;Specify
00500		4	;Parameter count.
00600		15	;Init
00700		=20	;Step rate in ms*2.
00800		=25	;Head settling time in ms*2.
00900		252	;H unload I cnt./ H load time.
01000		0
01100		0
01200	   SBT ← 10
01300		65	;Specify
01400		4
01500		20	;Surface zero bad tracks command.
01600		377	;No bad tracks.
01700		377
01800		0	;Current track.
01900		0
02000		0
02100	   DMA ← 20
02200		72	;Write special register.
02300		2
02400		27	;Mode register.
02500		2	;DMA and single actuator.
02600		0
02700		0
02800		0
02900		0
03000	   MON ← 30
03100		72	;Write special register.
03200		2
03300		43	;Drive control output register.
03400		40	;Optional output / motor on bit.
03500		0
03600		0
03700		0
03800		0
03900	   MOFF ← 40
04000		72	;Write special register.
04100		2
04200		43	;Drive control output register.
04300		0	;Optional output / motor off.
04400		0
04500		0
04600		0
04700		0
04800	   RHDR ← 50
04900		22	;Read one sector command.
05000		2
05100		0	;Header track number.
05200		0	;Header sector number.
05300		0
05400		0
05500		0
05600		0
05700	   WHDR ← 60
05800		12	;Write one sector command.
05900		2
06000		0	;Header track number.
06100		0	;Header sector number.
06200		0
06300		0
06400		0
06500		0
06600	   VHDR ← 70
06700		36	;Verify one sector command.
06800		2
06900		0	;Header track number.
07000		0	;Header sector number.
07100		0
07200		0
07300		0
07400		0
     

00100	;Power on reset.
00200	RST:	LDXI	377	;Setup stack.
00300		TXS
00400		CLD	;Clear decimal mode.
00500	
00600	;Reset I/O
00700	;Init floppy disk controller.
00800	   FDSKC ← FDSK		;Disk command/status register
00900	   FDSKP ← FDSK+1	;Disk parameter/result register
01000	   FDSKR ← FDSK+2	;Disk reset register.
01100	
01200		LDAI	1	;Reset disk again.
01300		STA	FDSKR
01400		LSRA	;Clear A
01500		STA	FDSKR
01600	
01700		LDAI	DINIT	;Disk initialization command.
01800		JSR	PCMD	;Prom command.
01900		LDAI	SBT	;Setup bad tracks
02000		JSR	PCMD
02100		LDAI	DMA	;Setup DMA mode.
02200		JSR	PCMD
02300	
02400	;Reset SI/O
02500	
02600	FOCLR:	LDAI	0
02650		STAZ	RFOPEN	;Reset read file open flag.
02700		STAZ	WFOPEN	;Clear write file open flag.
02800	;Reset command mode.
02900	DOFF:	LDAI	0
03000		STAZ	XFLG	;Set to command mode.
03100	
03200		CLI	;Enable interrupts.
03300	
03325	;Add cli and sei for interrupt bind?
03350	CLRER:	LDAI	0
03375		STAZ	ERFLG	;Clear error flag.
03387	
03400	IDLSET:	LDAI	0	;Reset idle mode.
03500		STAZ	CMD
03600	
03700	IDLE:	BITZ	ERFLG	;Check for error
03750		BMI	DOERO
03775	
03787		LDAZ	CMD	;Check for input.
03800		BEQ	IDLE
03900	;Non-interrupt level command decode.
04000		BITZ	NAMFLG	;Check if a file name.
04100		BPL	DCODE
04150	
04155		STAZX	FNAME	;Save file name.
04160		INX	;X = name index.
04165		CPXI	=9	;# of chrs. in file name.
04170		BPL	IDLESET	;Wait for the rest of name.
04175	
04180		INX
04185		STXZ	NAMFLG	;Reset name mode.
04190		RTS	;Return to command.
     

00100	DCODE:	LDXI	NCMDS	;# of commands.
00200	DL:	CMPX	CMDTBL	;Check if valid command.
00300		BEQ	JCMD
00400		DEX
00500		BPL	DL
00600	;Illegal command.
00700		LDAI	4	;Command error code.
00800	OACK:	JSR	OCHR	;Output status.
00900		JMP	IDLSET
01000	
01100	JCMD:	LDAX	JLTBL	;Get lsbyte of jump address.
01200		STAZ	CMDJMP
01300		LDAX	JHTBL	;Get msbyte.
01400		STAZ	CJMPH
01450	
01500		JMPIN	CMDJMP	;Excute command.
01600	
01700	   NCMDS ← UNDEF	;# of commands.
01800	CMDTBL:	"W"	;Write data
01900		"R"	;Read data
02000		"E"	;Enter write file.
02100		"C"	;Close write file.
02200		"O"	;Open read file.
02300		"K"	;Delete file.
02400		"D"	;Open directory.
02500		"N"	;Next directory block.
02600		"B"	;Free blp
02700		"F"	;Format disk.
02800		"I"	;Initialize directory.
02900		"Q"	;Compress holes.
03000	
03100	CJMPL:	WRT	;Lsbyte of command address.
03200		RD
03300		ENTR
03400		CLOZ
03500		OPIN
03600		KIL
03700		DIR
03800		NXTD
03900		BLKS
04000		FORM
04100		INITD
04200		CMPRES
04300	
04400	CJMPH:		;Msbyte of command address.
     

00100	;Write command to FDSKC
00200	RCMD:	LDAI	0	;Ram command.
00300		STAZ	FCMD
00400		STAZ	FCMDH
00500		BEQ	WCMD
00600	
00700	PCMD:	STAZ	FCMD	;Prom command.
00800		LDAI	PROM	;Command table addr.
00900		STAZ	FCMDH
01000	
01100	WCMD:	LDA	FDSKC	;Wait until not busy.
01200		BMI	WCMD
01300	
01400		LDYI	0
01500		LDAIY	FCMD	;Get command code.
01600		STA	FDSKC	;Write in disk cotrol reg.
01700		INCZ	FCMD	;Point to parameter count.
01800		LDAIY	FCMD	;Get count.
01900		BEQ	NOPAR	;If no parameters
02000		TAY
02100	
02200	PARW:	LDA	FDSKC	;Read status
02300		ANDI	40	;P reg full bit.
02400		BNE	PARW	;Wait if still full.
02500	
02600		LDAIY	FCMD	;Parameter
02700		STA	FDSKP
02800		DEY
02900		BNE	PARW	;More left?
03000	
03100	NOPAR:	RTS
     

00100	;IRQ maskable interrupt routines.
00200	IRQV:	PHA	;Save registers
00300		TYA
00400		PHA
00500		TXA
00600		PHA
00700	;Poll
00800		LDA	FDSKC	;Read disk status.
00900		ANDI	10	;IRQ bit
01000		BEQ	SIO
01100	
01200	;Disk interrupt.
01300	
01400	;SI/O interrupt.
01500	SIO:	LDYI	0	;No index.
01600	
01650	;Check for SI/O error.
01700	;Check if read or write.
01800	
01900	;Read SI/O
02000	RSIO:	LDA	SIOD	;Get byte from I/O
02100	
02200		BITZ	XFLG	;Check if command.
02300		BPL	BUFIT
02400	
02500		STAZ	CMD	;Save command.
02600		JMP	RTRN	;Return
02700	
02800	;SI/O to disk write buffer.
02900	BUFIT:	BITZ	BFFLG	;Check if write buffer full.
03000		BMI	BFERR	;Error
03100	
03200		STAIY	SPOINT	;Save it.
03300		JMP	INCSPO	;Increment SI/O buffer pointer.
     

00100	;Output byte to SI/O.
00200	WSIO:	BITZ	BFFLG	;Check if buffer empty.
00300		BMI	BFERR	;Buffer empty error.
00400	
00500		LDAIY	SPOINT	;Get byte from FBUF.
00600		STA	SIOD	;Output it.
00700	
00800	INCSPO:	CLC
00850		ADCZ	CKSUM	;Update check sum.
00875		STAZ	CKSUM
00887		INCZ	SPOINT
00900		BNE	RTRN
01000	
01100		LDAI	377
01200		STAZ	BFFLG	;Set buffer done flag.
01300	
01400		BITZ	OBEMTY	;Check if other buffer done.
01500		BMI	BFERR	;Buffer bind error.
01600	
01700		LDAZ	SPOH
01800		XORI	1	;Swap buffers.
01900		STAZ	SPOH
02000	
02100	RTRN:	PLA	;Restore registers
02200		TAX
02300		PLA
02400		TAY
02500		PLA
02600		RTI	;Return
     

00100	;Non-maskable DRQ interrupt.
00200	NMIV:	PHA	;Save registers
00300		TYA
00400		PHA
00500		LDYI	0	;No index.
00600	
00700		BITZ	DIRC	;Get direction.
00800		BMI	WDRQ	;Disk write.
00900	
01000		LDA	FDREG	;Read byte from disk.
01100	
01200		STAIY	DPOINT	;Save it in FBUF
01300		JMP	INCPO	;Increment disk buffer pointer.
01400	
01500	WDRQ:	LDAIY	DPOINT	;Get byte from FBUF.
01600		STA	FDREG	;Write in disk data register.
01700	
01800	INCPO:	INCZ	DPOINT
01900		BNE	NRTRN	;Return if not done with buffer
02000	
02100		LDAZ	DPOH
02200		XORI	1	;Swap buffers
02300		STAZ	DPOH
02400	
02500	NRTRN:	PLA	;Restore registers.
02600		TAY
02700		PLA
02800		RTI	;Return
     

00100	;Directory look up.
00200	LOKUP:	LDAI	377
00300		STAZ	NAMFLG	;Set get name.
00400		JSR	IDLE	;Wait for it.
00500	
00600		JSR	RDTRK	;Read first directory track.
00700		LDAZ	FBUF
00800		CMPI	DMARK	;Check for header.
00900		BEQ	BUMPIT
01000	;No directory.
01050	BUMPIT:	LDYI	20	;Skip directory block.
01100	CKDIR:	LDXI	0
01200	CKNAM:	LDAY	FBUF
01300		CMPZX	FBLK	;Look for file name.
01400		BNE	NXTF	;No match
01500		INY
01600		INX
01700		CPXI	=10	;9 chrs. + fmark
01800		BNE	CKNAM
01900	;Names match
02000	FMOV:	LDAY	FBUF	;Save file record.
02100		STAZX	FBLK
02200		INY
02300		INX
02400		CPXI	20
02500		BNE	FMOV
02600	
02700		LDAI	0	;Return with file found.
02800		RTS
02900	
03000	NXTF:	TYA	;Point to next file record.
03100		ORAI	17
03200		TAY
03300		INY
03400		BNE	CKDIR
03500	
03600		DECZ	SREM	;Check if more sectors.
03700		BNE	GETS
03750	FNF:	LDAI	200	;Return file not found code.
03775		RTS
03800	
03900	GETS:	INCZ	CSEC	;Next sector
03950	   ;No jsr?
04000		JSR	RNDS	;Read next directory sector.
04100		LDYI	0
04200		BEQ	CKDIR
     

     

00100	OPIN:	JSR	LOKUP	;Lookup file FNAM
00200		BEQ	SETOPN
00250	RERR:		;Disk read error.
00275		JMP	OACK	;Output error code.
00300	
00400	SEEK:	LDAZ	FTRK	;Get track and sector
00500		STAZ	CTRK
00600		LDAZ	FSEC
00700		STAZ	CSEC
00800		LDAI	377
00900		STAZ	RFOPEN
01000	GACK:	LDAI	6	;<ack>
01100		JMP	OACK
     

00100	SETBUF:	LDAI	FBUF	;Read disk into FBUF
00200		STAZ	FLAD	;Setup buffer pointer.
00300		ASLA	;Clear A
00400		STAZ	31	;FLAD+1
00500		LDXI	1	;X=1 For one sector
00600		RTS
00700	
00800	RBUF:	JSR	SETBUF	;Setup address
00900	
01000	;Read sectors from disk.
01100	READ:	JSR	FWAI	;Check if busy
01200		JSR	SETTO	;Init timer
01300		LDAI	143	;IBM read command (n secs)
01400		STA	FDSKC
01500	
01600	RSEC:	LDYI	0
01700	FLOAD:	LDA	DSKSEL	;Check if byte ready
01800		BPL	FLOAD
01900		LDA	FDSKD	;Read byte from disk
02000		STAIY	FLAD
02100		INY
02200		BPL	FLOAD
02300	
02400		LDAZ	FLAD
02500		EORI	200	;Next sector
02600		STAZ	FLAD
02700		BMI	NOPAGE
02800		INCZ	FLAD+1
02900	
03000	NOPAGE:	DEX
03100		BNE	RSEC	;More sectors
03200	
03300		JSR	ENDSK	;Reset disk, timer. Read status
03400		RTS
03500	
03600	ENDSK:	LDAI	57	;End disk op
03700		STA	FDSKC
03800		EOR	FDSKC	;Read disk status
03900		ANDI	376	;For busy bit
04000		RTS
     

00100	;Create file routine
00200	ENTR:	LDAZ	FFTRK
00250		CMPI	LASTRK	;Check if disk is full.
00275		BCC	LOKIT
00287	   ;Disk full
00293	LOKIT:	JSR	LOKUP	;Check if file already exists.
00300		BEQ	FEXIST	;Check if file exists
00400		CMPI	200	;Not in dir. code
00500		BEQ	GFBLK
00550	;Do disk error recovery.
00650	FEXIST:	LDAI	2	;File exists error code.
00750		JMP	OACK
00800	
00900	GFBLK:	LDAZ	FFTRK	;Get first free track.
01600		STAZ	CTRK
01700		LDAZ	FFSEC
01800		STAZ	CSEC
02300		LDAI	377	;Set write file open flag.
02400		STAZ	WFOPEN
02600		JMP	GACK	;Return with no errors
     

00100	WBUF:	JSR	SETBUF	;Write FBUF
00200	
00300	
00400	WRITE:	JSR	FWAI	;Check if busy.
00500		JSR	SETTO	;Init timer
00600	
00700		LDAI	103	;Write multiple sectors command
00800		STA	FDSKC
00900	
01000	CLRY:	LDYI	0
01100	WLOOP:	LDA	DSKSEL	;Wait until empty
01200		BPL	WLOOP
01300	
01400		LDAIY	FLAD
01500		STA	FDSKD	;Write chr on disk
01600		INY
01700		BPL	WLOOP
01800	
01900	QW:	LDA	DSKSEL	;Wait for 129th DRQ
02000		BPL	QW
02100		STA	FDSKD
02200	
02300		LDAZ	FLAD
02400		EORI	200	;Next sector
02500		STAZ	FLAD
02600		BMI	CKMOR
02700		INCZ	FLAD+1
02800	CKMOR:	DEX		;More sectors
02900		BNE	CLRY
03000	
03100		JSR	ENDSK	;Reset disk, timer. Read status
03200		BNE	WERR	;Verify if no errors
     

00100	;Verify disk write
00200	VERIFY:	LDAZ	FSEC	;Reset disk sector number
00300		STA	FDSKS
00400		JSR	SETTO	;Set timer
00500		LDXZ	NSEC	;Get number of sectors
00600		LDAI	147	;Read MS, HE.
00700		STA	FDSKC
00800	
00900	NXTS:	LDYI	0
01000	VWAI:	LDA	DSKSEL	;Wait for byte
01100		BPL	VWAI
01200		LDA	FDSKD	;Read byte
01300		INY
01400		BPL	VWAI	;Done with sector
01500	
01600		DEX
01700		BNE	NXTS	;Done with file
01800	
01900		JSR	ENDSK	;Reset disk, timer. Read status
02000	WERR:	RTS	;Return with error bits
     

00100	CLOZE:	BITZ	WFOPEN	;Check if file open
00200		BMI	UPDIR
00300	RERR:	LDAI	377	;Return with error
00400		RTS
00500	
00600	;Update directory
00700	UPDIR:	LDAI	377	;Get end of directory
00800		STAZ	FTRK
00900		LDXZ	SCNT	;Get sec.
01000		INX
01100		TXA
01200		EORI	377	;Invert it
01300		STAZ	FSEC
01400		STAZ	OSEC	
01500		JSR	SEEK
01600		BNE	RERR	;Seek error
01700		JSR	RBUF	;Read end of directory.
01800		BNE	RERR	;Read error
01900	
02000		LDAZ	FFTRK	;Point to new file
02100		STAZ	FTRK
02200		LDAZ	FFSEC
02300		STAZ	FSEC
02400	
02500		LDXZ	FFDIR
02600	
02700	;BLT FBLK into directory
02800		LDYI	0
02900	NAMEIT:	LDAY	FBLK
03000		STAZX	FBUF
03100		INX
03200		INY
03300		CPYI	20	;FBLK Length
03400		BNE	NAMEIT
03500	
03600		LDXZ	OSEC	;Point to end of directory
03700		STXZ	FSEC
03800	
03900		STX	FDSKS
04000		LDXZ	NSEC	;Save file length
04100		STXZ	FLEN
04200		LDXI	1	;For one sector
04300		STXZ	NSEC
04400		JSR	WBUF	;Write new file record
04500		BNE	RERR	;Check for write error
04600	
04700		INCZ	FCNT
04800		CLC
04900		LDAZ	FFDIR
05000		ADCI	20	;Update end of dir.
05100		BPL	SVSEC
05200		LDAI	0
05300		INCZ	SCNT	;Next sector
05400	
05500	SVSEC:	STAZ	FFDIR
05600	
05700		LDAZ	FFSEC
05800		SEC
05900		SBCZ	FLEN	;Point to next free sector.
06000		STAZ	FFSEC
06100	
06200		LDAI	375
06300		STA	FDSKS	;Start of directory
06400		JSR	RBUF	;Read directory header
06500		BNE	RERR	;Check for read error
06600	
06700		LDXI	1
06800		STXZ	NSEC
06900		LDXI	17	;Header length
07000	HLOOP:	LDAZX	DBUF	;BLT Header into directory
07100		STAZX	FBUF
07200		DEX
07300		BPL	HLOOP
07400	
07500		JSR	WBUF	;Write directory
07600		BNE	RERR	;Write error
07700		STAZ	WFOPEN	;Reset write file open flag
07800	
07900		RTS
     

00100	END